package com.vhly.ddxdecompiler.dexreader.file.dalv.code;

import com.vhly.classfile.CPInteger;
import com.vhly.classfile.ConstantPool;
import com.vhly.classfile.bytecode.*;

import java.io.ByteArrayOutputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.util.Vector;

/**
 * Created by IntelliJ IDEA.
 * User: vhly
 * Date: 2009-10-29
 * Time: 11:48:30
 *
 * @author vhly[FR]
 */
public class InsnConvert {

    public static void convert(DalvInsn insn, BCD bcd, ConstantPool cp) throws IOException {
        Dop opcode = insn.dexOpcode;
        Vector<Integer> regs = insn.registers;
        int op = opcode.getOpcode();
        int va, vb;
        switch (op) {
            case 0:  // nop
                bcd.add(new NOP());
                break;
            case 1: // move vA, vB   vB => vA
            case 2:
            case 3:
            case 4:
            case 5:
            case 6:
                va = regs.elementAt(0);
                vb = regs.elementAt(1);
                ILOAD iload = new ILOAD();
                iload.setArg(va);
                ISTORE istore = new ISTORE();
                istore.setArg(vb);
                bcd.add(iload);
                bcd.add(istore);
                break;
            case 7:
            case 8:
            case 9:
                va = regs.elementAt(0);
                vb = regs.elementAt(1);
                ALOAD aload = new ALOAD();
                aload.setArg(va);
                ASTORE astore = new ASTORE();
                astore.setArg(vb);
                bcd.add(aload);
                bcd.add(astore);
                break;
            case 10:
            case 11:
                va = regs.elementAt(0);
                istore = new ISTORE();
                istore.setArg(va);
                bcd.add(istore);
                break;
            case 0x0c:
                va = regs.elementAt(0);
                astore = new ASTORE();
                astore.setArg(va);
                bcd.add(astore);
                break;
            case 0x0d:
                ATHROW athrow = new ATHROW();
                bcd.add(athrow);
                break;
            case 0x0e:
                RETURN ret1 = new RETURN();
                bcd.add(ret1);
                break;
            case 0x0f:
                IRETURN ireturn = new IRETURN();
                bcd.add(ireturn);
                break;
            case 0x10:
                LRETURN lreturn = new LRETURN();
                bcd.add(lreturn);
                break;
            case 0x11:
                ARETURN areturn = new ARETURN();
                bcd.add(areturn);
                break;
            case 0x12:
            case 0x13:
                /*
                const/4 vA, #+B
                const/16 vA, #+BBBB
                	A: destination register (4 bits)
                    B: signed int (4 bits)
                    Move the given literal value (sign-extended to 32 bits) into the specified register.
                 */
                va = regs.elementAt(0);
                vb = regs.elementAt(1);
                SIPUSH sipush = new SIPUSH();
                sipush.setArg(vb);
                istore = new ISTORE();
                istore.setArg(va);
                bcd.add(sipush);
                bcd.add(istore);
                break;
            case 0x14:
                /*
                const vAA, #+BBBBBBBB
                    A: destination register (8 bits)
                    B: arbitrary 32-bit constant
                Move the given literal value into the specified register.
                 */
                va = regs.elementAt(0);
                vb = regs.elementAt(1);
                CPInteger ci = new CPInteger(vb);
                int index = cp.indexOf(ci);
                if (index == -1) {
                    index = cp.addCPEntry(ci) - 1;
                }
                LDC ldc = new LDC();
                ldc.setIndex(index);
                istore = new ISTORE();
                istore.setArg(va);
                bcd.add(ldc);
                bcd.add(istore);
                break;
            case 0x54:
                /*
                iget-object vA, vB, field@CCCC

                get B.CCCC to A
                 */

                va = regs.elementAt(0);
                vb = regs.elementAt(1);
                int vc = regs.elementAt(2);
                aload = new ALOAD();
                aload.setArg(vb);
                GETFIELD getfield = new GETFIELD();
                getfield.setArg(vc);
                astore = new ASTORE();
                astore.setArg(va);
                bcd.add(aload);
                bcd.add(getfield);
                bcd.add(astore);
                break;
            case 0x5b: // 91
                // iput-object va, vb, field@CCCC
                va = regs.elementAt(0);
                vb = regs.elementAt(1);
                vc = regs.elementAt(2);
                aload = new ALOAD();
                aload.setArg(va);
                ALOAD aload1 = new ALOAD();
                aload1.setArg(vb);
                PUTFIELD putfield = new PUTFIELD();
                putfield.setIndex(vc);
                bcd.add(aload);
                bcd.add(aload1);
                bcd.add(putfield);
                break;
            case 0x70:
                // invoke-direct
                System.out.println("opcode = " + opcode);
                break;
            case 0x55: // 85
//                break;
            case 0x56: // 86
//                break;
            case 0x57: // 87
//                break;
            case 0x58: // 88
//                break;
            case 0x59: // 89
//                break;
            case 0x5a: // 90
//                break;
            default: //
                throw new UnsupportedOperationException("bytecode convert unsport code " + opcode);
        }
    }
}
